﻿/**
* jQuery Extensions / Plugins
*
* Created by Bendy on March 3, 2012.
* jQuery official website: http://jquery.com/
*
*/

$.fn.extend({

    /**
    * Check whether the value is number. If not, then show the message.
    * 
    * @example $('#inputAge').isNumber(['Please input a number.']);
    *
    * @param String message The message for invalid value.
    * @return true, If value is number. Otherwise, false.
    * @type Boolean
    */
    __isNumber: function (message) {
        var val = $(this).val();

        if (val.length === 0 || isNaN(val)) {
            alert(message);
            return false;
        }

        return true;
    },

    /**
    * Attach the style for a LIST.
    * 
    * @example listStyle('tr', 'evenClass'[, 'hoverClass'][, 'selectedClass']);
    *
    * @param String itemTag The tag of repeat item.
    * @param String evenStyle The style(Class Name) of even item.
    * @param String hoverStyle The Style(Class Name) for when the cursor over.
    * @param String selected The Style(Class Name) for when current item is clicked.
    */
    __listStyle: function (itemTag, evenStyle, hoverStyle, selectedStyle) {
        var cssOriginal = '';
        $('#' + this.attr('id') + ' ' + itemTag + ':odd').addClass(evenStyle);

        if (typeof hoverStyle !== undefined) {
            $('#' + this.attr('id') + ' ' + itemTag).mouseover(function () {
                cssOriginal = $(this).attr('class');
                $(this).addClass(hoverStyle);
            });
            $('#' + this.attr('id') + ' ' + itemTag).mouseout(function () {
                $(this).removeClass(hoverStyle);
            });
        }

        if (typeof selectedStyle !== undefined) {
            $('#' + this.attr('id') + ' ' + itemTag).click(function () {
                $(this).toggleClass(selectedStyle, cssOriginal);
            });
        }
    },

    /**
    * Fix the position for a element in browser window.
    *
    * @example fixPosition(100, 300);
    * 
    * @param Number x The position of X axes.
    * @param Number y the position of Y axes.
    */
    __fixPosition: function (x, y) {
        $(this).css({
            position: 'fixed',
            left: x,
            top: y
        });

        // For MSIE
        if ($.browser.msie) {
            $(this).css({
                position: 'absolute',
                left: x,
                top: y
            });

            var originalTop = $(this).position().top;
            var obj = $(this);
            window.attachEvent('onscroll', function () {
                var newTop = document.documentElement.scrollTop + originalTop;
                obj.css('top', newTop);
            });
        }
    },

    /**
    * Copy inner html of a special element to a container.
    *
    * @example $('#id').cloneTo('divContainer');
    * @param String targetId The ID of the container. 
    *       If empty or not be defined, this clone will be attached after current element.
    */
    __cloneTo: function (targetId) {
        var tmpName = '__cloneTo__';

        if ($('#' + tmpName).length > 0) {
            $('#' + tmpName).val(parseInt($('#' + tmpName).val()) + 1);
        }
        else {
            $('<input type="hidden" id="' + tmpName + '" value="0" />').appendTo('body');
        }

        var idx = $('#' + tmpName).val();

        var jObj = $(this).clone(true);

        jObj.find('input').each(function () {
            var newId = $(this).attr('id').split('_')[0] + '_' + idx;
            $(this).attr('id', newId);
        });

        if (typeof targetId === 'undefined' || targetId.length === 0) {
            jObj.insertAfter(this);
        }
        else {
            $('#' + targetId).append(jObj);
        }
    },

    /**
    * Select or unselect All.
    * 
    * @example $('#all').select($('input[type=checkbox]'));
    * @param String selector jQuery selector for check box.
    */
    __toggleSelect: function (selector) {
        $(this).click(function () {

            var status = $(this).attr('checked');

            if (typeof selector !== 'undefined' && selector.length > 0) {
                $(selector).attr('checked', status);
            }
            else {
                $('input[type=checkbox]').attr('checked', status);
            }
        });
    },

    /**
    * Inverse the selected item.
    *
    * @example $('#btnInverse').inverseSelect('input[type=checkbox]');
    * @param String selector jQuery selector for check box.
    */
    __inverseSelect: function (selector) {
        $(this).click(function () {

            if (typeof selector === 'undefined' || selector.length === 0) {
                selector = 'input[type=checkbox]';
            }

            $(selector).each(function () {
                var val = $(this).attr('checked');
                $(this).attr('checked', val == true ? false : true);
            });
        });
    },

    /**
    * Submit the form with validating.
    *   Form Input: <input type='textbox' validate='[required,number,length(6,10),date,email]' />
    *
    * @example $('#btnSubmit').clickToSubmitForm('form1');
    * @param Strign formId The ID of the form that need to be validated.
    */
    __clickToSubmitForm: function (formId) {
        var msgInvalid = 'Invalid Data.';
        var msgRequired = 'This field is required.';
        var msgNumber = 'Please enter a number.';
        var msgEmail = 'Invalid Email Address.';
        var msgDate = 'Invalid Date.'
        var msgLength = 'String length is not valid.';

        if (typeof (formId) === 'undefined' || formId.length === 0) {
            formId = document.forms[0].id;
        }

        $(this).click(function () {
            var frm = $('#' + formId);
            var validateResult = true;

            frm.find('*[validate]').each(function () {
                var val = $(this).val();
                var chks = $(this).attr('validate').split(',');

                for (var i = 0; i < chks.length; i++) {
                    var reg;
                    switch (chks[i].replace(' ', '')) {
                        case 'required':
                            if (val.length == 0) {
                                alert(msgRequired);
                                validateResult = false;
                            }
                            break;
                        case 'number':
                            if (isNaN(val)) {
                                alert(msgNumber);
                                validateResult = false;
                            }
                            break;
                        case 'email':
                            reg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/;
                            if (!reg.test(val)) {
                                alert(msgEmail);
                                validateResult = false;
                            }
                            break;
                        case 'date':
                            // format: 2012-03-08
                            reg = /^((\d{2}(([02468][048])|([13579][26]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))))|(\d{2}(([02468][1235679])|([13579][01345789]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\s(((0?[0-9])|([1-2][0-3]))\:([0-5]?[0-9])((\s)|(\:([0-5]?[0-9])))))?$/;
                            validateResult = reg.test(val);
                            // format: 3/18/2012
                            reg = /^((0?[1-9])|(1[012]))\/((0?[1-9])|([12][0-9])|(3[01]))\/(\d{4})$/;
                            if (!validateResult) {
                                validateResult = reg.test(val);
                            }

                            if (!validateResult) {
                                alert(msgDate);
                            }
                            break;

                        default:
                            if (chks[i].indexOf('length') >= 0) {
                                var array = chks[i].replace('length(', '').replace(')', '').replace(' ', '').split('-');
                                var minLength = array[0].length > 0 ? parseInt(array[0]) : -1;
                                var maxLength = array.length > 1 && array[1].length > 0 ? parseInt(array[1]) : -1;

                                if (minLength != -1 && val.length < minLength) {
                                    validateResult = false;
                                }

                                if (maxLength != -1 && val.length > maxLength) {
                                    validateResult = false;
                                }

                                if (!validateResult) {
                                    alert(msgLength);
                                }
                            }

                            if (chks[i].indexOf('reg') >= 0) {
                                var p = eval(chks[i].replace('reg(', '').replace(')', ''));
                                if (typeof (p) != 'undefined' && !p.test(val)) {
                                    alert(msgInvalid);
                                    validateResult = false;
                                }
                            }

                            break;
                    }

                    if (!validateResult) {
                        $(this).focus();
                        // step out of cycle for validating a element. 
                        return false;
                    }
                }

                if (!validateResult) {
                    // step out of cycle for validating all elements. 
                    return false;
                }
            });

            if (validateResult) {
                frm.submit();
            }
        });
    },

    /** 
    * Create a sub menu for a main menu.
    *       When mouse over it, the sub menu will be displayed. Otherwise, hidden.
    * @example $('#menuA').subMenu('<a href="sub menu1">Sub Menu1</a>', '<a href="sub menu2">Sub Menu2</a>');
    * @param String arguments Sub menu items.
    */
    __subMenu: function () {
        var args = arguments;
        var id = Math.floor(Math.random() * 10000);
        var container = $('<div id="__subMenu__' + id + '" style="position:relative; top:0px; left:0px; display:none;"></div>');

        for (var i = 0; i < args.length; i++) {
            var item = $('<div></div>');
            $(args[i]).appendTo(item);
            item.appendTo(container);
        }
        container.appendTo($(this));


        $(this).bind('mouseover', function (args) {
            var sm = $('#__subMenu__' + id);
            if (sm) {
                sm.show();
            }
        });

        $(this).bind('mouseout', function () {
            var sm = $('#__subMenu__' + id);
            if (sm) {
                sm.hide();
            }
        });
    }
});